package bll

import (
	"fmt"
	"strconv"

	"7qule.com/sd3/CrossServer/src/bll/challenge/dal"
	. "7qule.com/sd3/CrossServer/src/bll/challenge/model"
	"7qule.com/sd3/CrossServer/src/bll/world"
	"7qule.com/sd3/CrossServer/src/common/onlinelog"
	"7qule.com/sd3/CrossServer/src/common/systemConstant"
	"public.com/goutil/syncUtil"
)

type globalChallengeBll struct {
	// 用户擂台的信息
	data map[string]*GlobalChallengeModel

	// 数据同步对象
	dataLock *syncUtil.RWLocker
}

var GlobalChallengeBll = &globalChallengeBll{
	dataLock: syncUtil.NewRWLocker(),
}

// --------------------------------初始化--------------------------------------------------

// 初始化
func init() {
	// 注册数据初始化函数
	world.LoadMgr.RegisterFunc(GlobalChallengeBll.StructName(), GlobalChallengeBll.initData)
}

// StructName 模块名
func (this *globalChallengeBll) StructName() string {
	return "GlobalChallengeBll"
}

//
// initData
// @Description: 初始化数据
// @receiver this
// @return errList:错误信息
//
func (this *globalChallengeBll) initData() (errList []error) {
	tempList, err := dal.GlobalChallengeDal.GetData()
	if err != nil {
		errList = append(errList, err)
		return
	}

	tempMap := make(map[string]*GlobalChallengeModel)

	if len(tempList) == 0 {
		configStage := BaseChallengeStageModelBll.GetData()

		for i := 1; i <= 100; i++ {
			for stageId := range configStage {
				NewChallengeRobot := NewGlobalChallengeRobot(strconv.Itoa(stageId)+"_"+strconv.Itoa(i), stageId, i)
				dal.GlobalChallengeDal.Insert(NewChallengeRobot)
				tempMap[NewChallengeRobot.PlayerId] = NewChallengeRobot
			}
		}
		this.data = tempMap

		GlobalChallengeStageBll.InitData()
		GlobalChallengeLeaderboardBll.InitData()

		return
	}

	for _, item := range tempList {
		tempMap[item.PlayerId] = item
	}

	this.data = tempMap

	GlobalChallengeStageBll.InitData()
	GlobalChallengeLeaderboardBll.InitData()
	return
}

// --------------------------------生成的基础方法---------------------------------------------

//
// GetData
// @Description: 获取数据
// @receiver this
// @return map[string]*GlobalChallengeModel:用户擂台数据
//
func (this *globalChallengeBll) GetData() map[string]*GlobalChallengeModel {
	return this.data
}

// --------------------------------内部方法--------------------------------------------------

//
// insert
// @Description: 插入数据
// @receiver this
// @param data:数据对象
//
func (this *globalChallengeBll) insert(data *GlobalChallengeModel) {
	dal.GlobalChallengeDal.Insert(data)
}

//
// update
// @Description:更新数据
// @receiver this
// @param data:数据对象
//
func (this *globalChallengeBll) update(data *GlobalChallengeModel) {
	dal.GlobalChallengeDal.Update(data)
}

//
// delete
// @Description:删除数据
// @receiver this
// @param data:数据对象
//
func (this *globalChallengeBll) delete(data *GlobalChallengeModel) {
	dal.GlobalChallengeDal.Delete(data)
}

//
// getChallengePlayerData
// @Description:获取用户擂台比武信息
// @receiver this
// @param playerId:玩家id
// @return result:用户信息
// @return exist:是否存在
//
func (this *globalChallengeBll) getChallengePlayerData(playerId string) (result *GlobalChallengeModel, exist bool) {
	if isOk, prevStack, currStack := this.dataLock.RLock(systemConstant.DefaultLockTime); isOk == false {
		errMsg := fmt.Sprintf("Lock timeout! \n上一个堆栈:\n%s  \n当前堆栈:\n%s", prevStack, currStack)
		onlinelog.ErrorLog(errMsg)
		panic(errMsg)
	}
	defer this.dataLock.RUnlock()

	result, exist = this.data[playerId]
	return
}

//
// addChallengePlayerData
// @Description:添加用户擂台信息
// @receiver this
// @param data:用户擂台信息
//
func (this *globalChallengeBll) addChallengePlayerData(data *GlobalChallengeModel) {
	if isOk, prevStack, currStack := this.dataLock.Lock(systemConstant.DefaultLockTime); isOk == false {
		errMsg := fmt.Sprintf("Lock timeout! \n上一个堆栈:\n%s  \n当前堆栈:\n%s", prevStack, currStack)
		onlinelog.ErrorLog(errMsg)
		panic(errMsg)
	}
	defer this.dataLock.Unlock()

	this.data[data.PlayerId] = data
}

// --------------------------------外部方法--------------------------------------------------

//
// GetChallenge
// @Description:获取用户擂台比武信息
// @receiver this
// @param playerId:玩家id
// @return result:用户信息
// @return exist:是否存在
//
func (this *globalChallengeBll) GetChallengePlayer(playerId string) (result *GlobalChallengeModel, exist bool) {
	result, exist = this.getChallengePlayerData(playerId)
	return
}

//
// UpdateChallengePlayer
// @Description:修改用户擂台信息
// @receiver this
// @param playerId:用户id
// @param stageId:页签id
// @param rank:排名
// @param IsRobot:是否是机器人
// @return *GlobalChallengeModel:用户信息
//
func (this *globalChallengeBll) UpdateChallengePlayer(playerId string, stageId, rank int, IsRobot bool) *GlobalChallengeModel {
	// 读锁
	playerChallengeData, exist := this.getChallengePlayerData(playerId)
	if !exist {
		playerChallengeData = NewGlobalChallenge2(playerId, stageId, rank)
		// 写锁
		this.addChallengePlayerData(playerChallengeData)

		this.insert(playerChallengeData)

		return playerChallengeData
	}

	playerChallengeData.StageId = stageId
	playerChallengeData.Rank = rank
	playerChallengeData.IsRobot = IsRobot

	this.update(playerChallengeData)

	return playerChallengeData
}

//
// UpdateChallengePlayerToRobot
// @Description:修改用户为机器人
// @receiver this
// @param playerId:用户id
// @param stageId:页签id
// @param rank:排名
// @return *GlobalChallengeModel:机器人信息
//
func (this *globalChallengeBll) UpdateChallengePlayerToRobot(playerId string, stageId, rank int) *GlobalChallengeModel {
	robotId := strconv.Itoa(stageId) + "_" + playerId + "_" + "Robot"
	robotChallenge := NewGlobalChallengeRobot(robotId, stageId, rank)
	this.UpdateChallengePlayer(robotChallenge.PlayerId, robotChallenge.StageId, robotChallenge.Rank, robotChallenge.IsRobot)

	return robotChallenge
}

//
// AssembleToClient
// @Description:组装数据
// @receiver this
// @param playerId:用户id
// @return map[string]interface{}:数据
//
func (this *globalChallengeBll) AssembleToClient(playerId string) map[string]interface{} {
	// 对返回结果先赋初值
	resultMap := make(map[string]interface{}, 2)

	// 获取自己排名
	data, exists := this.getChallengePlayerData(playerId)
	if !exists {
		return resultMap
	}
	resultMap["MyRanking"] = data.Rank

	return resultMap
}
